home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Sample.bin / jre_main.c < prev    next >
C/C++ Source or Header  |  1998-09-15  |  11KB  |  435 lines

  1. /*
  2.  * @(#)jre_main.c    1.14 98/07/01
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. /*
  16.  * Main program for invoking application with JRE (Java Runtime Environment)
  17.  */
  18.  
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <jni.h>
  23. #include "jre.h"
  24.  
  25. /* Name of this program */
  26. #define PROGRAM "jre"
  27.  
  28. /* Title of this program */
  29. #ifdef VERSION
  30. #define TITLE "Java(tm) Runtime Loader Version " VERSION
  31. #else
  32. #define TITLE "Java(tm) Runtime Loader"
  33. #endif
  34.  
  35. /* Check for null value and return */
  36. #define NULL_CHECK(e) if ((e) == 0) return 0
  37.  
  38. /* Enable debugging output */
  39. #ifdef JRE_DEBUG
  40. jboolean debug;
  41. #endif
  42.  
  43.  
  44. /* Forward declarations */
  45. jint ParseOptions(int *argcp, char ***argvp, JDK1_1InitArgs *vmargs);
  46. void AddProperty(char *def);
  47. void DeleteProperty(const char *name);
  48. void PrintUsage(void);
  49. jarray NewStringArray(JNIEnv *env, char **cpp, int count);
  50. long atoml(char *s);
  51.  
  52. /* Globals */
  53. static char **props;        /* User-defined properties */
  54. static int numProps, maxProps;    /* Current, max number of properties */
  55.  
  56. /*
  57.  * Main program to invoke Java runtime using JNI invocation API. Supports
  58.  * setting of VM arguments through standard command line options.
  59.  */
  60. void main(int argc, char *argv[])
  61. {
  62.     JRESettings set;
  63.     void *handle;
  64.     JDK1_1InitArgs vmargs;
  65.     JavaVM *jvm;
  66.     JNIEnv *env;
  67.     char *s, *name;
  68.     jclass cls;
  69.     jmethodID mid;
  70.     jarray args;
  71.     int i;
  72.  
  73.     /* First scan arguments for help and debug options */
  74.     for (i = 1; i < argc; i++) {
  75.     char *arg = argv[i];
  76.     if (*arg++ != '-') {
  77.         break;
  78.     }
  79.     if (strcmp(arg, "?") == 0 || strcmp(arg, "h") == 0 ||
  80.         strcmp(arg, "help") == 0) {
  81.         PrintUsage();
  82.         exit(1);
  83.     }
  84. #ifdef JRE_DEBUG
  85.     if (strcmp(arg, "d") == 0) {
  86.         debug = JNI_TRUE;
  87.     }
  88. #endif
  89.     }
  90.  
  91.     /* Get runtime settings */
  92. #ifdef VERSION
  93.     if (JRE_GetSettings(&set, VERSION) != 0) {
  94. #else
  95.     if (JRE_GetCurrentSettings(&set) != 0) {
  96. #endif
  97.     if (JRE_GetDefaultSettings(&set) != 0) {
  98.         fprintf(stderr, "Could not locate Java runtime\n");
  99.         exit(1);
  100.     }
  101.     }
  102.  
  103. #ifdef JRE_DEBUG
  104.     if (debug) {
  105.     char *ver = JRE_MakeVersion(set.majorVersion, set.minorVersion,
  106.                     set.microVersion);
  107.     fprintf(stderr, "Runtime Settings:\n");
  108.     fprintf(stderr, " javaHome   = %s\n",
  109.         set.javaHome != 0 ? set.javaHome : "<not set>");
  110.     fprintf(stderr, " runtimeLib = %s\n",
  111.         set.runtimeLib != 0 ? set.runtimeLib : "<not set>");
  112.     fprintf(stderr, " version    = %s\n", ver != 0 ? ver : "<not set>");
  113.     fprintf(stderr, " compiler   = %s\n\n",
  114.         set.compiler != 0 ? set.compiler : "<not set>");
  115.     }
  116. #endif
  117.  
  118.     /* Load runtime library */
  119.     handle = JRE_LoadLibrary(set.runtimeLib);
  120.     if (handle == 0) {
  121.     fprintf(stderr, "Could not load runtime library: %s\n",
  122.         set.runtimeLib);
  123.     exit(1);
  124.     }
  125.  
  126.     /* Add pre-defined system properties */
  127.     if (set.javaHome != 0) {
  128.     char *def = JRE_Malloc(strlen(set.javaHome) + 16);
  129.     sprintf(def, "java.home=%s", set.javaHome);
  130.     AddProperty(def);
  131.     }
  132.     if (set.compiler != 0) {
  133.     char *def = JRE_Malloc(strlen(set.compiler) + 16);
  134.     sprintf(def, "java.compiler=%s", set.compiler);
  135.     AddProperty(def);
  136.     }
  137.  
  138.     /*
  139.      * The following is used to specify that we require at least
  140.      * JNI version 1.1. Currently, this field is not checked but
  141.      * will be starting with JDK/JRE 1.2. The value returned after
  142.      * calling JNI_GetDefaultJavaVMInitArgs() is the actual JNI version
  143.      * supported, and is always higher that the requested version.
  144.      */
  145.     vmargs.version = 0x00010001;
  146.  
  147.     if (JRE_GetDefaultJavaVMInitArgs(handle, &vmargs) != 0) {
  148.     fprintf(stderr, "Could not initialize Java VM\n");
  149.     exit(1);
  150.     }
  151.     vmargs.classpath = set.classPath;
  152.  
  153.     /* Parse command line options */
  154.     --argc; argv++;
  155.     if (ParseOptions(&argc, &argv, &vmargs) != 0) {
  156.     PrintUsage();
  157.     exit(1);
  158.     }
  159.  
  160.     /* Get name of class */
  161.     if (*argv == 0) {
  162.     PrintUsage();
  163.     exit(1);
  164.     }
  165.     name = strdup(*argv++);
  166.     for (s = name; *s != '\0'; s++) {
  167.     if (*s == '.') *s = '/';
  168.     }
  169.     --argc;
  170.  
  171. #ifdef JRE_DEBUG
  172.     if (debug) {
  173.     fprintf(stderr, "CLASSPATH is %s\n\n", vmargs.classpath);
  174.     }
  175. #endif
  176.  
  177.     /* Set user-defined system properties for Java VM */
  178.     if (props != 0) {
  179.     if (numProps == maxProps) {
  180.         char **tmp = JRE_Malloc((numProps + 1) * sizeof(char **));
  181.         memcpy(tmp, props, numProps * sizeof(char **));
  182.         free(props);
  183.         props = tmp;
  184.     }
  185.     props[numProps] = 0;
  186.     vmargs.properties = props;
  187.     }
  188.  
  189.     /* Load and initialize Java VM */
  190.     if (JRE_CreateJavaVM(handle, &jvm, &env, &vmargs) != 0) {
  191.     fprintf(stderr, "Could not create Java VM\n");
  192.     exit(1);
  193.     }
  194.  
  195.     /* Free properties */
  196.     if (props != 0) {
  197.     free(props);
  198.     }
  199.  
  200.     /* Find class */
  201.     cls = (*env)->FindClass(env, name);
  202.     if (cls == 0) {
  203.     fprintf(stderr, "Class not found: %s\n", *--argv);
  204.     exit(1);
  205.     }
  206.  
  207.     /* Find main method of class */
  208.     mid = (*env)->GetStaticMethodID(env, cls, "main",
  209.                         "([Ljava/lang/String;)V");
  210.     if (mid == 0) {
  211.     fprintf(stderr, "In class %s: public static void main(String args[])"
  212.             " is not defined\n");
  213.     exit(1);
  214.     }
  215.  
  216.     /* Invoke main method */
  217.     args = NewStringArray(env, argv, argc);
  218.  
  219.     if (args == 0) {
  220.     JRE_FatalError(env, "Couldn't build argument list for main\n");
  221.     }
  222.     (*env)->CallStaticVoidMethod(env, cls, mid, args);
  223.     if ((*env)->ExceptionOccurred(env)) {
  224.     (*env)->ExceptionDescribe(env);
  225.     }
  226.  
  227.     /* Wait until we are the only user thread remaining then unload VM */
  228.     (*jvm)->DestroyJavaVM(jvm);
  229.  
  230.     /* Unload the runtime */
  231.     JRE_UnloadLibrary(handle);
  232. }
  233.  
  234. /*
  235.  * Parses command line VM options. Returns 0 if successful otherwise
  236.  * returns -1 if an invalid option was encountered.
  237.  */
  238. jint ParseOptions(int *argcp, char ***argvp, JDK1_1InitArgs *vmargs)
  239. {
  240.     char *arg, **argv = *argvp;
  241.  
  242.     while ((arg = *argv++) != 0 && *arg++ == '-') {
  243.     if (strcmp(arg, "classpath") == 0) {
  244.         if (*argv == 0) {
  245.         fprintf(stderr, "No class path given for %s option\n", arg);
  246.         return -1;
  247.         }
  248.         vmargs->classpath = *argv++;
  249.     } else if (strcmp(arg, "cp") == 0) {
  250.         char *cp = vmargs->classpath;
  251.         if (*argv == 0) {
  252.         fprintf(stderr, "No class path given for %s option\n", arg);
  253.         return -1;
  254.         }
  255.         vmargs->classpath = malloc(strlen(*argv) + strlen(cp) + 2);
  256.         if (vmargs->classpath == 0) {
  257.         perror("malloc");
  258.         exit(1);
  259.         }
  260.         sprintf(vmargs->classpath, "%s%c%s", *argv++, PATH_SEPARATOR, cp);
  261.     } else if (strncmp(arg, "D", 1) == 0) {
  262.         AddProperty(arg + 1);
  263.     } else if (strncmp(arg, "ss", 2) == 0) {
  264.         jint n = atoml(arg + 2);
  265.         if (n >= 1000) {
  266.         vmargs->nativeStackSize = n;
  267.         }
  268.     } else if (strncmp(arg, "oss", 3) == 0) {
  269.         jint n = atoml(arg + 3);
  270.         if (n >= 1000) {
  271.         vmargs->javaStackSize = n;
  272.         }
  273.     } else if (strncmp(arg, "ms", 2) == 0) {
  274.         jint n = atoml(arg + 2);
  275.         if (n >= 1000) {
  276.         vmargs->minHeapSize = n;
  277.         }
  278.     } else if (strncmp(arg, "mx", 2) == 0) {
  279.         jint n = atoml(arg + 2);
  280.         if (n >= 1000) {
  281.         vmargs->maxHeapSize = n;
  282.         }
  283.     } else if (strcmp(arg, "noasyncgc") == 0) {
  284.         vmargs->disableAsyncGC = JNI_TRUE;
  285.     } else if (strcmp(arg, "noclassgc") == 0) {
  286.         vmargs->enableClassGC = JNI_FALSE;
  287.     } else if (strcmp(arg, "verify") == 0) {
  288.         vmargs->verifyMode = 2;
  289.     } else if (strcmp(arg, "verifyremote") == 0) {
  290.         vmargs->verifyMode = 1;
  291.     } else if (strcmp(arg, "noverify") == 0) {
  292.         vmargs->verifyMode = 0;
  293.     } else if (strcmp(arg, "nojit") == 0) {
  294.         /**
  295.          * Set the value of java.compiler equal to the empty 
  296.          * string.  At the jit library loading step nothing will
  297.          * loaded.
  298.          */
  299.         AddProperty("java.compiler=");
  300.     } else if (strcmp(arg, "v") == 0 || strcmp(arg, "verbose") == 0) {
  301.         vmargs->verbose = JNI_TRUE;
  302. #ifdef JRE_DEBUG
  303.     } else if (strcmp(arg, "d") == 0) {
  304.         debug = JNI_TRUE;
  305. #endif
  306.     } else if (strcmp(arg, "verbosegc") == 0) {
  307.         vmargs->enableVerboseGC = JNI_TRUE;
  308.     } else if (strcmp(arg, "?") == 0 || strcmp(arg, "h") == 0 ||
  309.            strcmp(arg, "help") == 0) {
  310.         return -1;
  311.     } else {
  312.         fprintf(stderr, "Illegal option: -%s\n", arg);
  313.         return -1;
  314.     }
  315.     }
  316.     *argcp -= --argv - *argvp;
  317.     *argvp = argv;
  318.     return 0;
  319. }
  320.  
  321. /*
  322.  * Adds a user-defined system property definition.
  323.  */
  324. void AddProperty(char *def)
  325. {
  326.     if (numProps >= maxProps) {
  327.     if (props == 0) {
  328.         maxProps = 4;
  329.         props = JRE_Malloc(maxProps * sizeof(char **));
  330.     } else {
  331.         char **tmp;
  332.         maxProps *= 2;
  333.         tmp = JRE_Malloc(maxProps * sizeof(char **));
  334.         memcpy(tmp, props, numProps * sizeof(char **));
  335.         free(props);
  336.         props = tmp;
  337.     }
  338.     }
  339.     props[numProps++] = def;
  340. }
  341.  
  342. /*
  343.  * Deletes a property definition by name.
  344.  */
  345. void DeleteProperty(const char *name)
  346. {
  347.     int i;
  348.  
  349.     for (i = 0; i < numProps; ) {
  350.     char *def = props[i];
  351.     char *c = strchr(def, '=');
  352.     int n;
  353.     if (c != 0) {
  354.         n = c - def;
  355.     } else {
  356.         n = strlen(def);
  357.     }
  358.     if (strncmp(name, def, n) == 0) {
  359.         if (i < --numProps) {
  360.         memmove(&props[i], &props[i+1], (numProps-i) * sizeof(char **));
  361.         }
  362.     } else {
  363.         i++;
  364.     }
  365.     }
  366. }
  367.  
  368. /*
  369.  * Creates an array of Java string objects from the specified array of C
  370.  * strings. Returns 0 if the array could not be created.
  371.  */
  372. jarray NewStringArray(JNIEnv *env, char **cpp, int count)
  373. {
  374.     jclass cls;
  375.     jarray ary;
  376.     int i;
  377.  
  378.     NULL_CHECK(cls = (*env)->FindClass(env, "java/lang/String"));
  379.     NULL_CHECK(ary = (*env)->NewObjectArray(env, count, cls, 0));
  380.     for (i = 0; i < count; i++) {
  381.     jstring str = (*env)->NewStringUTF(env, *cpp++);
  382.     NULL_CHECK(str);
  383.     (*env)->SetObjectArrayElement(env, ary, i, str);
  384.     (*env)->DeleteLocalRef(env, str);
  385.     }
  386.     return ary;
  387. }
  388.  
  389. /*
  390.  * Parses a memory size specification from the specified C string.
  391.  */
  392. long atoml(char *s)
  393. {
  394.     long n = strtol(s, &s, 10);
  395.     switch (*s++) {
  396.     case 'M': case 'm':
  397.     n *= 1024 * 1024;
  398.     break;
  399.     case 'K': case 'k':
  400.     n *= 1024;
  401.     break;
  402.     case '\0':
  403.     return n;
  404.     default:
  405.     return -1;
  406.     }
  407.     return *s == '\0' ? n : -1;
  408. }
  409.  
  410. /*
  411.  * Prints help message.
  412.  */
  413. void PrintUsage()
  414. {
  415.     fprintf(stderr, TITLE "\n"
  416.     "Usage: " PROGRAM " [-options] classname [arguments]\n"
  417.     "Options:\n"
  418.     "    -?, -help         print out this message\n"
  419.     "    -v, -verbose      turn on verbose mode\n"
  420.     "    -verbosegc        print a message when garbage collection occurs\n"
  421.     "    -noasyncgc        disable asynchronous garbage collection\n"
  422.     "    -noclassgc        disable class garbage collection\n"
  423.     "    -ss<number>       set the maximum native stack size for any thread\n"
  424.     "    -oss<number>      set the maximum Java stack size for any thread\n"
  425.     "    -ms<number>       set the initial Java heap size\n"
  426.     "    -mx<number>       set the maximum Java heap size\n"
  427.     "    -D<name>=<value>  set a system property\n"
  428.     "    -classpath <path> set class path to <path>\n"
  429.     "    -cp <path>        prepend <path> to base class path\n"
  430.     "    -verify           verify all classes when loaded\n"
  431.     "    -verifyremote     verify classes loaded from the network (default)\n"
  432.     "    -noverify         do not verify any classes\n"
  433.     "    -nojit            disable JIT compiler\n");
  434. }
  435.